Computer programs have become increasingly more complex as they provide more and more features. As the complexity increases, the probability that a computer program will have a programming error (commonly referred to as a “bug”) increases dramatically. To reduce the probability of distributing a computer program with a programming error, developers of computer program perform extensive testing. Because of the importance of thorough testing and because such testing can be very time-consuming, computer program developers have developed extensive testing procedures.
In order to make a computer program application reliable for its intended audience, whether that be a commercial distribution of thousands of copies as a major software product offering to the public at large, or internal use distribution, as a tool to a department sized work group of a dozen people or less, the area of software testing has emerged as the primary vehicle for assuring quality software products and for rooting out and resolving as many bugs as possible. In the field of testing, an attempt is made to exercise the software in as many different ways as possible in order to catch as many programming errors as possible before “releasing” the software for general use. Bugs not caught before release are very costly to an enterprise both in terms of rectifying the errors and in the loss of goodwill due to perceptions regarding the quality of the software.
Computer program code is tested using one of a number of conventional methods, including artificially simulating a fault condition by stepping through the executable file in a debugger and manually changing the instruction pointer or memory value, modifying the source code by introducing debug statements or routines into the program and observing the results during program execution, limiting system resources, writing replacement function libraries using user controllable settings, or intercepting functions at run-time and diverting control execution to a replacement function.
Another technique is redirecting a function, as in U.S. Pat. No. 5,812,828, in which a call to a function is replaced with a call to a user-supplied function. However, this technique suffers from the same drawback that all techniques that use a replacement function suffer from: the location, or entry point address, of the original redirected function is not retained, therefore, the original redirected function cannot be accessed. In this case, the original redirected function is merely simulated, the original redirected function is never used or accessed by the user-supplied function. This limits developers and testers in the testing of the function because the original function must often be used to exactly reproduce a fault.